home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / OutOfPhase1.01Source / OutOfPhase Folder / OscBankPlayer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-01  |  33.4 KB  |  977 lines  |  [TEXT/KAHL]

  1. /* OscBankPlayer.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #define ShowMeFrozenNoteRec
  31. #define ShowMe_NoteObjectRec
  32. #include "OscBankPlayer.h"
  33. #include "LFOGenerator.h"
  34. #include "IncrementalParameterUpdator.h"
  35. #include "LFOSpecifier.h"
  36. #include "LFOListSpecifier.h"
  37. #include "Memory.h"
  38. #include "Array.h"
  39. #include "OscillatorListSpecifier.h"
  40. #include "OscillatorSpecifier.h"
  41. #include "InstrumentStructure.h"
  42. #include "GenInstrTopology.h"
  43. #include "SampleOscControl.h"
  44. #include "WaveTableOscControl.h"
  45. #include "ModulationOscControl.h"
  46. #include "DeterminedNoteStructure.h"
  47. #include "NoteObject.h"
  48. #include "FloatingPoint.h"
  49. #include "Frequency.h"
  50. #include "ErrorDaemon.h"
  51.  
  52.  
  53. typedef struct
  54.     {
  55.         /* this is the reference to the template object */
  56.         void*                                        TemplateReference;
  57.  
  58.         /* perform one envelope update cycle */
  59.         void                                        (*UpdateEnvelopes)(void* State);
  60.         /* dispose of the state record */
  61.         void                                        (*DisposeState)(void* State);
  62.         /* dispose of the information template */
  63.         void                                        (*DisposeTemplate)(void* Template);
  64.         /* create a new state object. */
  65.         void*                                        (*NewState)(void* Template,
  66.                                                             float FreqForMultisampling, float Accent1, float Accent2,
  67.                                                             float Accent3, float Accent4, float Loudness, float HurryUp,
  68.                                                             long* PreOriginTimeOut, float StereoPosition,
  69.                                                             float InitialFrequency);
  70.         /* fix up pre-origin time for the state object */
  71.         void                                        (*FixUpStatePreOrigin)(void* State, long ActualPreOrigin);
  72.         /* set a new frequency for a state object.  used for portamento */
  73.         /* and modulation of frequency (vibrato) */
  74.         void                                        (*StateNewFrequency)(void* State, float NewFrequencyHertz);
  75.         /* send a key-up signal to one of the oscillators */
  76.         void                                        (*KeyUpSustain1)(void* State);
  77.         void                                        (*KeyUpSustain2)(void* State);
  78.         void                                        (*KeyUpSustain3)(void* State);
  79.         /* restart a oscillator.  this is used for tie continuations */
  80.         void                                        (*RestartState)(void* State, float NewFreqMultisampling,
  81.                                                             float NewAccent1, float NewAccent2, float NewAccent3,
  82.                                                             float NewAccent4, float NewLoudness, float NewHurryUp,
  83.                                                             MyBoolean RetriggerEnvelopes, float NewStereoPosition,
  84.                                                             float NewInitialFrequency,
  85.                                                             float NewLoudnessLFOAmplitudeScaling,
  86.                                                             float NewLoudnessLFOFrequencyScaling);
  87.         /* generate a sequence of samples (called for each envelope clock) */
  88.         void                                        (*GenSamples)(void* State, long SampleCount,
  89.                                                             largefixedsigned* RawBuffer);
  90.         /* find out if the oscillator has finished yet */
  91.         MyBoolean                                (*IsItFinished)(void* State);
  92.     } OscBankVectorRec;
  93.  
  94.  
  95. struct OscBankTemplateRec
  96.     {
  97.         /* general parameters */
  98.         MyBoolean                                StereoOutput;
  99.         float                                        OverallVolumeScalingFactor;
  100.         long                                        SamplingRate;
  101.         float                                        EnvelopeUpdateRate;
  102.         MyBoolean                                TimeInterpolation;
  103.         MyBoolean                                WaveInterpolation;
  104.  
  105.         /* parameter updator for track (so we can set up individual notes properly) */
  106.         IncrParamUpdateRec*            ParamUpdator;
  107.  
  108.         /* template for the pitch displacement LFO */
  109.         LFOListSpecRec*                    PitchLFOTemplate;
  110.  
  111.         /* instrument overall loudness */
  112.         float                                        InstrOverallLoudness;
  113.  
  114.         /* list of template records describing each oscillator */
  115.         OscBankVectorRec*                TemplateArray;
  116.         /* this is the number of oscillators in the array */
  117.         long                                        NumOscillatorsInBank;
  118.     };
  119.  
  120.  
  121. typedef struct OscStateRec
  122.     {
  123.         /* this is a reference to the state object for this oscillator */
  124.         void*                                        StateReference;
  125.  
  126.         /* copy of the routine vectors */
  127.         OscBankVectorRec                Template;
  128.  
  129.         /* next oscillator in the list */
  130.         struct OscStateRec*            Next;
  131.     } OscStateRec;
  132.  
  133.  
  134. struct OscStateBankRec
  135.     {
  136.         /* what are we derived from */
  137.         OscBankTemplateRec*            BankTemplate;
  138.  
  139.         /* list of oscillators that this oscillator bank is comprised of */
  140.         OscStateRec*                        OscillatorList;
  141.  
  142.         /* this calculates the differential values for periodic pitch displacements */
  143.         LFOGenRec*                            PitchLFO;
  144.  
  145.         /* if this object ties to a note, then this is the note to tie to.  this is */
  146.         /* used for finding existing oscillators for tie continuations. */
  147.         struct NoteObjectRec*        TieToNote;
  148.  
  149.         /* portamento control parameters */
  150.         long                                        PortamentoCounter; /* 0 = done */
  151.         long                                        TotalPortamentoTicks;
  152.         float                                        InitialFrequency;
  153.         float                                        FinalFrequency;
  154.         float                                        CurrentFrequency;
  155.         /* True = portamento linear to Hertz; False = portamento linear to half-steps */
  156.         MyBoolean                                PortamentoHertz;
  157.         MyBoolean                                PitchLFOHertz;
  158.  
  159.         /* various counters (in terms of envelope ticks) */
  160.         /* negative = expired */
  161.         long                                        Release1Countdown;
  162.         long                                        Release2Countdown;
  163.         long                                        Release3Countdown;
  164.         long                                        PitchLFOStartCountdown;
  165.  
  166.         /* next oscillator bank in the list */
  167.         struct OscStateBankRec*    Next;
  168.     };
  169.  
  170.  
  171. static OscStateRec*                            StateFreeList = NIL;
  172. static OscStateBankRec*                    StateBankFreeList = NIL;
  173.  
  174.  
  175. /* flush all cached oscillator state bank records */
  176. void                                    FlushCachedOscStateBankRecords(void)
  177.     {
  178.         while (StateBankFreeList != NIL)
  179.             {
  180.                 OscStateBankRec*        Temp;
  181.  
  182.                 Temp = StateBankFreeList;
  183.                 StateBankFreeList = StateBankFreeList->Next;
  184.                 ReleasePtr((char*)Temp);
  185.             }
  186.  
  187.         while (StateFreeList != NIL)
  188.             {
  189.                 OscStateRec*                Temp;
  190.  
  191.                 Temp = StateFreeList;
  192.                 StateFreeList = StateFreeList->Next;
  193.                 ReleasePtr((char*)Temp);
  194.             }
  195.     }
  196.  
  197.  
  198. #if DEBUG
  199. static void                    ValidateOscState(OscStateRec* State)
  200.     {
  201.         OscStateRec*            Scan;
  202.  
  203.         CheckPtrExistence(State);
  204.         Scan = StateFreeList;
  205.         while (Scan != NIL)
  206.             {
  207.                 if (Scan == State)
  208.                     {
  209.                         PRERR(ForceAbort,"ValidateOscState:  state object is on free list");
  210.                     }
  211.                 Scan = Scan->Next;
  212.             }
  213.     }
  214. #else
  215. #define ValidateOscState(x) ((void)0)
  216. #endif
  217.  
  218.  
  219. #if DEBUG
  220. static void                    ValidateOscStateBank(OscStateBankRec* StateBank)
  221.     {
  222.         OscStateBankRec*    Scan;
  223.  
  224.         CheckPtrExistence(StateBank);
  225.         Scan = StateBankFreeList;
  226.         while (Scan != NIL)
  227.             {
  228.                 if (Scan == StateBank)
  229.                     {
  230.                         PRERR(ForceAbort,"ValidateOscStateBank:  state bank object is on free list");
  231.                     }
  232.                 Scan = Scan->Next;
  233.             }
  234.     }
  235. #else
  236. #define ValidateOscStateBank(x) ((void)0)
  237. #endif
  238.  
  239.  
  240. /* construct an oscillator bank template record.  various parameters are passed in */
  241. /* which are needed for synthesis.  ParameterUpdator is the parameter information */
  242. /* record for the whole track of which this is a part. */
  243. OscBankTemplateRec*        NewOscBankTemplate(struct InstrumentRec* InstrumentDefinition,
  244.                                                 MyBoolean StereoFlag, LargeBCDType OverallVolumeScalingReciprocal,
  245.                                                 long SamplingRate, float EnvelopeRate, MyBoolean TimeInterp,
  246.                                                 MyBoolean WaveInterp, struct IncrParamUpdateRec* ParameterUpdator,
  247.                                                 ErrorDaemonRec* ErrorDaemon)
  248.     {
  249.         OscBankTemplateRec*    Template;
  250.         ArrayRec*                        TwoDOscList;
  251.         OscillatorListRec*    OscillatorListObject;
  252.         OscillatorRec**            OscillatorVector;
  253.         long                                Scan;
  254.  
  255.         CheckPtrExistence(InstrumentDefinition);
  256.         CheckPtrExistence(ParameterUpdator);
  257.         CheckPtrExistence(ErrorDaemon);
  258.  
  259.         Template = (OscBankTemplateRec*)AllocPtrCanFail(sizeof(OscBankTemplateRec),
  260.             "OscBankTemplateRec");
  261.         if (Template == NIL)
  262.             {
  263.              FailurePoint1:
  264.                 return NIL;
  265.             }
  266.  
  267.         /* the oscillator bank template contains all of the information needed for */
  268.         /* constructing oscillators as notes are to be executed. */
  269.         /* number of oscillators in a bank. */
  270.         OscillatorListObject = GetInstrumentOscillatorList(InstrumentDefinition);
  271.         OscillatorVector = (OscillatorRec**)AllocPtrCanFail(sizeof(OscillatorRec*)
  272.             * GetOscillatorListLength(OscillatorListObject),"OscillatorRec[]");
  273.         if (OscillatorVector == NIL)
  274.             {
  275.              FailurePoint2:
  276.                 ReleasePtr((char*)Template);
  277.                 goto FailurePoint1;
  278.             }
  279.         for (Scan = 0; Scan < GetOscillatorListLength(OscillatorListObject); Scan += 1)
  280.             {
  281.                 PRNGCHK(OscillatorVector,&(OscillatorVector[Scan]),sizeof(OscillatorVector[Scan]));
  282.                 OscillatorVector[Scan] = GetOscillatorFromList(OscillatorListObject,Scan);
  283.             }
  284.         TwoDOscList = BuildOscillatorLists(OscillatorVector,
  285.             GetOscillatorListLength(OscillatorListObject));
  286.         if (TwoDOscList == NIL)
  287.             {
  288.              FailurePoint3:
  289.                 ReleasePtr((char*)OscillatorVector);
  290.                 goto FailurePoint2;
  291.             }
  292.  
  293.         /* get LFO information */
  294.         Template->PitchLFOTemplate = GetInstrumentFrequencyLFOList(InstrumentDefinition);
  295.  
  296.         /* vector containing templates for all of the oscillators */
  297.         Template->TemplateArray = (OscBankVectorRec*)AllocPtrCanFail(
  298.             sizeof(OscBankVectorRec) * ArrayGetLength(TwoDOscList),
  299.             "OscBankVectorRec");
  300.         if (Template->TemplateArray == NIL)
  301.             {
  302.              FailurePoint4:
  303.                 for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  304.                     {
  305.                         DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  306.                     }
  307.                 DisposeArray(TwoDOscList);
  308.                 goto FailurePoint3;
  309.             }
  310.  
  311.         Template->NumOscillatorsInBank = 0;
  312.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  313.             {
  314.                 ArrayRec*                    OneOscArray;
  315.  
  316.                 OneOscArray = (ArrayRec*)ArrayGetElement(TwoDOscList,Scan);
  317.                 CheckPtrExistence(OneOscArray);
  318.                 if ((ArrayGetLength(OneOscArray) == 1) && (GetModulationSpecNumEntries(
  319.                     OscillatorGetModulatorInputList((OscillatorRec*)ArrayGetElement(
  320.                     OneOscArray,0))) == 0))
  321.                     {
  322.                         OscillatorRec*        Osc;
  323.  
  324.                         Osc = (OscillatorRec*)ArrayGetElement(OneOscArray,0);
  325.                         CheckPtrExistence(Osc);
  326.                         switch (OscillatorGetWhatKindItIs(Osc))
  327.                             {
  328.                                 default:
  329.                                     EXECUTE(PRERR(ForceAbort,"NewOscBankTemplate:  bad oscillator type"));
  330.                                     break;
  331.                                 case eOscillatorSampled:
  332.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  333.                                         sizeof(Template->TemplateArray[Scan]));
  334.                                     Template->TemplateArray[Scan].TemplateReference
  335.                                         = NewSampleTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  336.                                         TimeInterp,WaveInterp,ErrorDaemon);
  337.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  338.                                         {
  339.                                          FailurePoint5:
  340.                                             for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  341.                                                 {
  342.                                                     (*Template->TemplateArray[Scan]
  343.                                                         .DisposeTemplate)(Template->TemplateArray[
  344.                                                         Scan].TemplateReference);
  345.                                                 }
  346.                                             goto FailurePoint4;
  347.                                         }
  348.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  349.                                         = (void (*)(void*))&UpdateSampleEnvelopes;
  350.                                     Template->TemplateArray[Scan].DisposeState
  351.                                         = (void (*)(void*))&DisposeSampleState;
  352.                                     Template->TemplateArray[Scan].DisposeTemplate
  353.                                         = (void (*)(void*))&DisposeSampleTemplate;
  354.                                     Template->TemplateArray[Scan].NewState
  355.                                         = (void* (*)(void*,float,float,float,float,float,
  356.                                         float,float,long*,float,float))&NewSampleState;
  357.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  358.                                         = (void (*)(void*,long))&FixUpSampleStatePreOrigin;
  359.                                     Template->TemplateArray[Scan].StateNewFrequency
  360.                                         = (void (*)(void*,float))&SampleStateNewFrequency;
  361.                                     Template->TemplateArray[Scan].KeyUpSustain1
  362.                                         = (void (*)(void*))&SampleKeyUpSustain1;
  363.                                     Template->TemplateArray[Scan].KeyUpSustain2
  364.                                         = (void (*)(void*))&SampleKeyUpSustain2;
  365.                                     Template->TemplateArray[Scan].KeyUpSustain3
  366.                                         = (void (*)(void*))&SampleKeyUpSustain3;
  367.                                     Template->TemplateArray[Scan].RestartState
  368.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  369.                                         MyBoolean,float,float,float,float))&RestartSampleState;
  370.                                     Template->TemplateArray[Scan].GenSamples
  371.                                         = (void (*)(void*,long,largefixedsigned*))&SampleGenSamples;
  372.                                     Template->TemplateArray[Scan].IsItFinished
  373.                                         = (MyBoolean (*)(void*))&SampleIsItFinished;
  374.                                     break;
  375.                                 case eOscillatorWaveTable:
  376.                                     PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  377.                                         sizeof(Template->TemplateArray[Scan]));
  378.                                     Template->TemplateArray[Scan].TemplateReference
  379.                                         = NewWaveTableTemplate(Osc,EnvelopeRate,SamplingRate,StereoFlag,
  380.                                         TimeInterp,WaveInterp,ErrorDaemon);
  381.                                     if (Template->TemplateArray[Scan].TemplateReference == NIL)
  382.                                         {
  383.                                             goto FailurePoint5;
  384.                                         }
  385.                                     Template->TemplateArray[Scan].UpdateEnvelopes
  386.                                         = (void (*)(void*))&UpdateWaveTableEnvelopes;
  387.                                     Template->TemplateArray[Scan].DisposeState
  388.                                         = (void (*)(void*))&DisposeWaveTableState;
  389.                                     Template->TemplateArray[Scan].DisposeTemplate
  390.                                         = (void (*)(void*))&DisposeWaveTableTemplate;
  391.                                     Template->TemplateArray[Scan].NewState
  392.                                         = (void* (*)(void*,float,float,float,float,float,
  393.                                         float,float,long*,float,float))&NewWaveTableState;
  394.                                     Template->TemplateArray[Scan].FixUpStatePreOrigin
  395.                                         = (void (*)(void*,long))&FixUpWaveTableStatePreOrigin;
  396.                                     Template->TemplateArray[Scan].StateNewFrequency
  397.                                         = (void (*)(void*,float))&WaveTableStateNewFrequency;
  398.                                     Template->TemplateArray[Scan].KeyUpSustain1
  399.                                         = (void (*)(void*))&WaveTableKeyUpSustain1;
  400.                                     Template->TemplateArray[Scan].KeyUpSustain2
  401.                                         = (void (*)(void*))&WaveTableKeyUpSustain2;
  402.                                     Template->TemplateArray[Scan].KeyUpSustain3
  403.                                         = (void (*)(void*))&WaveTableKeyUpSustain3;
  404.                                     Template->TemplateArray[Scan].RestartState
  405.                                         = (void (*)(void*,float,float,float,float,float,float,float,
  406.                                         MyBoolean,float,float,float,float))&RestartWaveTableState;
  407.                                     Template->TemplateArray[Scan].GenSamples
  408.                                         = (void (*)(void*,long,largefixedsigned*))&WaveTableGenSamples;
  409.                                     Template->TemplateArray[Scan].IsItFinished
  410.                                         = (MyBoolean (*)(void*))&WaveTableIsItFinished;
  411.                                     break;
  412.                             }
  413.                     }
  414.                  else
  415.                     {
  416.                         PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  417.                             sizeof(Template->TemplateArray[Scan]));
  418.                         Template->TemplateArray[Scan].TemplateReference
  419.                             = NewModOscTemplate(OneOscArray,EnvelopeRate,SamplingRate,StereoFlag,
  420.                             TimeInterp,WaveInterp,ErrorDaemon);
  421.                         if (Template->TemplateArray[Scan].TemplateReference == NIL)
  422.                             {
  423.                                 goto FailurePoint5;
  424.                             }
  425.                         Template->TemplateArray[Scan].UpdateEnvelopes
  426.                             = (void (*)(void*))&UpdateModOscEnvelopes;
  427.                         Template->TemplateArray[Scan].DisposeState
  428.                             = (void (*)(void*))&DisposeModOscState;
  429.                         Template->TemplateArray[Scan].DisposeTemplate
  430.                             = (void (*)(void*))&DisposeModOscTemplate;
  431.                         Template->TemplateArray[Scan].NewState
  432.                             = (void* (*)(void*,float,float,float,float,float,
  433.                             float,float,long*,float,float))&NewModOscState;
  434.                         Template->TemplateArray[Scan].FixUpStatePreOrigin
  435.                             = (void (*)(void*,long))&FixUpModOscStatePreOrigin;
  436.                         Template->TemplateArray[Scan].StateNewFrequency
  437.                             = (void (*)(void*,float))&ModOscStateNewFrequency;
  438.                         Template->TemplateArray[Scan].KeyUpSustain1
  439.                             = (void (*)(void*))&ModOscKeyUpSustain1;
  440.                         Template->TemplateArray[Scan].KeyUpSustain2
  441.                             = (void (*)(void*))&ModOscKeyUpSustain2;
  442.                         Template->TemplateArray[Scan].KeyUpSustain3
  443.                             = (void (*)(void*))&ModOscKeyUpSustain3;
  444.                         Template->TemplateArray[Scan].RestartState
  445.                             = (void (*)(void*,float,float,float,float,float,float,float,
  446.                             MyBoolean,float,float,float,float))&RestartModOscState;
  447.                         Template->TemplateArray[Scan].GenSamples
  448.                             = (void (*)(void*,long,largefixedsigned*))&ModOscGenSamples;
  449.                         Template->TemplateArray[Scan].IsItFinished
  450.                             = (MyBoolean (*)(void*))&ModOscIsItFinished;
  451.                     }
  452.                 Template->NumOscillatorsInBank += 1;
  453.             }
  454.  
  455.         /* playback control parameters */
  456.         Template->StereoOutput = StereoFlag;
  457.         Template->OverallVolumeScalingFactor = 1.0 / LargeBCD2Single(OverallVolumeScalingReciprocal);
  458.         Template->SamplingRate = SamplingRate;
  459.         Template->EnvelopeUpdateRate = EnvelopeRate;
  460.         Template->TimeInterpolation = TimeInterp;
  461.         Template->WaveInterpolation = WaveInterp;
  462.  
  463.         Template->ParamUpdator = ParameterUpdator;
  464.  
  465.         Template->InstrOverallLoudness = GetInstrumentOverallLoudness(InstrumentDefinition);
  466.  
  467.         /* clean up the mess */
  468.         for (Scan = 0; Scan < ArrayGetLength(TwoDOscList); Scan += 1)
  469.             {
  470.                 DisposeArray((ArrayRec*)ArrayGetElement(TwoDOscList,Scan));
  471.             }
  472.         DisposeArray(TwoDOscList);
  473.         ReleasePtr((char*)OscillatorVector);
  474.  
  475.         return Template;
  476.     }
  477.  
  478.  
  479. /* dispose of the template */
  480. void                                    DisposeOscBankTemplate(OscBankTemplateRec* Template)
  481.     {
  482.         long                                Scan;
  483.  
  484.         CheckPtrExistence(Template);
  485.  
  486.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  487.             {
  488.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  489.                     sizeof(Template->TemplateArray[Scan]));
  490.                 (*Template->TemplateArray[Scan].DisposeTemplate)(Template->
  491.                     TemplateArray[Scan].TemplateReference);
  492.             }
  493.         ReleasePtr((char*)Template->TemplateArray);
  494.  
  495.         ReleasePtr((char*)Template);
  496.     }
  497.  
  498.  
  499. /* construct a new oscillator bank state object based on the note.  the note is */
  500. /* assumed to start "now" in terms of the parameters in the ParameterUpdator.  */
  501. /* the ScanningGapWidth is the number of envelope clock ticks in the current scanning */
  502. /* gap.  this is used to determine how far later than "now" in terms of the back */
  503. /* edge of the scanning gap (different from above) the osc bank should start playing. */
  504. /* *WhenToStartPlayingOut returns the number of envelope ticks after the back edge */
  505. /* of the scanning gap that the note should be started. */
  506. /*     <already played>       |    <scanning gap>     |    <not yet analyzed> */
  507. /*   time ---->    time ---->    time ---->    time ---->    time ---->   time ----> */
  508. /*                            ^A                      ^B     */
  509. /* point A is the back edge of the scanning gap.  as this edge moves forward in time, */
  510. /*   oscillator bank state objects are removed from the queue and playback is commenced */
  511. /*   for them. */
  512. /* point B is the front edge of the scanning gap.  as this edge moves forward in time, */
  513. /*   notes are extracted from the track and state bank objects are created for them. */
  514. /*   ParameterUpdator always reflects parameters at this point in time. */
  515. OscStateBankRec*            NewOscBankState(OscBankTemplateRec* Template,
  516.                                                 long* WhenToStartPlayingOut, struct NoteObjectRec* Note,
  517.                                                 float EnvelopeTicksPerDurationTick)
  518.     {
  519.         OscStateBankRec*        State;
  520.         long                                Scan;
  521.         FrozenNoteRec*            FrozenNote;
  522.         long                                StartPointAdjust;
  523.         long                                MaxOscillatorPreOriginTime;
  524.         OscStateRec*                OneState;
  525.         long                                ThisPreOriginTime;
  526.  
  527.         CheckPtrExistence(Template);
  528.         CheckPtrExistence(Note);
  529.  
  530.         if (StateBankFreeList != NIL)
  531.             {
  532.                 State = StateBankFreeList;
  533.                 StateBankFreeList = StateBankFreeList->Next;
  534.             }
  535.          else
  536.             {
  537.                 State = (OscStateBankRec*)AllocPtrCanFail(sizeof(OscStateBankRec),"OscStateBankRec");
  538.                 if (State == NIL)
  539.                     {
  540.                      FailurePoint1:
  541.                         return NIL;
  542.                     }
  543.             }
  544.         EXECUTE(State->Next = (OscStateBankRec*)0x81818181;)
  545.  
  546.         State->BankTemplate = Template;
  547.  
  548.         /* freeze the parameters */
  549.         FrozenNote = FixNoteParameters(Template->ParamUpdator,Note,&StartPointAdjust,
  550.             Template->OverallVolumeScalingFactor,EnvelopeTicksPerDurationTick);
  551.         if (FrozenNote == NIL)
  552.             {
  553.              FailurePoint2:
  554.                 State->Next = StateBankFreeList;
  555.                 StateBankFreeList = State;
  556.                 goto FailurePoint1;
  557.             }
  558.  
  559.         /* list of oscillators that this oscillator bank is comprised of */
  560.         State->OscillatorList = NIL;
  561.         MaxOscillatorPreOriginTime = 0;
  562.         for (Scan = 0; Scan < Template->NumOscillatorsInBank; Scan += 1)
  563.             {
  564.                 /* allocate the new record */
  565.                 if (StateFreeList != NIL)
  566.                     {
  567.                         OneState = StateFreeList;
  568.                         StateFreeList = StateFreeList->Next;
  569.                     }
  570.                  else
  571.                     {
  572.                         OneState = (OscStateRec*)AllocPtrCanFail(sizeof(OscStateRec),"OscStateRec");
  573.                         if (OneState == NIL)
  574.                             {
  575.                              FailurePoint3:
  576.                                 while (State->OscillatorList != NIL)
  577.                                     {
  578.                                         /* delink object */
  579.                                         OneState = State->OscillatorList;
  580.                                         State->OscillatorList = State->OscillatorList->Next;
  581.                                         /* dispose members */
  582.                                         (*OneState->Template.DisposeState)(OneState->StateReference);
  583.                                         /* stick on free list */
  584.                                         OneState->Next = StateFreeList;
  585.                                         StateFreeList = OneState;
  586.                                     }
  587.                                 goto FailurePoint2;
  588.                             }
  589.                     }
  590.  
  591.                 /* copy over the function vectors */
  592.                 PRNGCHK(Template->TemplateArray,&(Template->TemplateArray[Scan]),
  593.                     sizeof(Template->TemplateArray[Scan]));
  594.                 OneState->Template = Template->TemplateArray[Scan];
  595.  
  596.                 /* create the oscillator */
  597.                 OneState->StateReference = (OneState->Template.NewState)(
  598.                     OneState->Template.TemplateReference,FrozenNote->MultisampleFrequency,
  599.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  600.                     FrozenNote->LoudnessAdjust * Template->InstrOverallLoudness,
  601.                     FrozenNote->HurryUpFactor,&ThisPreOriginTime,FrozenNote->StereoPosition,
  602.                     FrozenNote->NominalFrequency);
  603.                 if (OneState->StateReference == NIL)
  604.                     {
  605.                      FailurePoint3a:
  606.                         OneState->Next = StateFreeList;
  607.                         StateFreeList = OneState;
  608.                         goto FailurePoint3;
  609.                     }
  610.  
  611.                 if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  612.                     {
  613.                         MaxOscillatorPreOriginTime = ThisPreOriginTime;
  614.                     }
  615.  
  616.                 /* link it in */
  617.                 OneState->Next = State->OscillatorList;
  618.                 State->OscillatorList = OneState;
  619.             }
  620.  
  621.         /* this calculates the differential values for periodic pitch displacements */
  622.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  623.         if (!State->PitchLFOHertz)
  624.             {
  625.                 /* half steps */
  626.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  627.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  628.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  629.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit / 12,
  630.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithGeometric,
  631.                     FrozenNote->MultisampleFrequency);
  632.             }
  633.          else
  634.             {
  635.                 State->PitchLFO = NewLFOGenerator(Template->PitchLFOTemplate,&ThisPreOriginTime,
  636.                     FrozenNote->Accent1,FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  637.                     FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  638.                     Template->EnvelopeUpdateRate,FrozenNote->PitchDisplacementDepthLimit,
  639.                     FrozenNote->PitchDisplacementRateLimit,eLFOArithAdditive,
  640.                     FrozenNote->MultisampleFrequency);
  641.             }
  642.         if (State->PitchLFO == NIL)
  643.             {
  644.              FailurePoint4:
  645.                 goto FailurePoint3;
  646.             }
  647.         if (ThisPreOriginTime > MaxOscillatorPreOriginTime)
  648.             {
  649.                 MaxOscillatorPreOriginTime = ThisPreOriginTime;
  650.             }
  651.  
  652.         /* if this object ties to a note, then this is the note to tie to.  this is */
  653.         /* used for finding existing oscillators for tie continuations. */
  654.         State->TieToNote = Note->a.Note.Tie;
  655.  
  656.         /* portamento control parameters */
  657.         State->PortamentoCounter = 0;
  658.         State->CurrentFrequency = FrozenNote->NominalFrequency;
  659.  
  660.         /* fix up pre-origin times */
  661.         OneState = State->OscillatorList;
  662.         while (OneState != NIL)
  663.             {
  664.                 (*OneState->Template.FixUpStatePreOrigin)(OneState->StateReference,
  665.                     MaxOscillatorPreOriginTime);
  666.                 OneState = OneState->Next;
  667.             }
  668.         LFOGeneratorFixEnvelopeOrigins(State->PitchLFO,MaxOscillatorPreOriginTime);
  669.  
  670.         /* various counters (in terms of envelope ticks) */
  671.         if (State->TieToNote == NIL)
  672.             {
  673.                 State->Release1Countdown = FrozenNote->ReleasePoint1
  674.                     + MaxOscillatorPreOriginTime;
  675.                 State->Release2Countdown = FrozenNote->ReleasePoint2
  676.                     + MaxOscillatorPreOriginTime;
  677.                 State->Release3Countdown = FrozenNote->ReleasePoint3
  678.                     + MaxOscillatorPreOriginTime;
  679.             }
  680.          else
  681.             {
  682.                 /* for ties, only honor releases from start */
  683.                 if (FrozenNote->Release1FromStart)
  684.                     {
  685.                         State->Release1Countdown = FrozenNote->ReleasePoint1
  686.                             + MaxOscillatorPreOriginTime;
  687.                     }
  688.                  else
  689.                     {
  690.                         State->Release1Countdown = -1;
  691.                     }
  692.                 if (FrozenNote->Release2FromStart)
  693.                     {
  694.                         State->Release2Countdown = FrozenNote->ReleasePoint2
  695.                             + MaxOscillatorPreOriginTime;
  696.                     }
  697.                  else
  698.                     {
  699.                         State->Release2Countdown = -1;
  700.                     }
  701.                 if (FrozenNote->Release3FromStart)
  702.                     {
  703.                         State->Release3Countdown = FrozenNote->ReleasePoint3
  704.                             + MaxOscillatorPreOriginTime;
  705.                     }
  706.                  else
  707.                     {
  708.                         State->Release3Countdown = -1;
  709.                     }
  710.             }
  711.         State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint
  712.             + MaxOscillatorPreOriginTime;
  713.  
  714.         /* clean up */
  715.         DisposeFrozenNote(FrozenNote);
  716.  
  717.         *WhenToStartPlayingOut = StartPointAdjust - MaxOscillatorPreOriginTime;
  718.  
  719.         return State;
  720.     }
  721.  
  722.  
  723. /* this is used for resetting a note for a tie */
  724. /* the FrozenNote object is NOT disposed */
  725. MyBoolean                            ResetOscBankState(OscStateBankRec* State,
  726.                                                 struct FrozenNoteRec* FrozenNote,
  727.                                                 float EnvelopeTicksPerDurationTick)
  728.     {
  729.         OscStateRec*                OneState;
  730.         MyBoolean                        RetriggerEnvelopes;
  731.  
  732.         CheckPtrExistence(State);
  733.         ValidateOscStateBank(State);
  734.         CheckPtrExistence(FrozenNote);
  735.  
  736.         RetriggerEnvelopes = ((FrozenNote->OriginalNote->Flags
  737.             & eRetriggerEnvelopesOnTieFlag) != 0);
  738.  
  739.         /* go through the oscillators and retrigger them */
  740.         OneState = State->OscillatorList;
  741.         while (OneState != NIL)
  742.             {
  743.                 (*OneState->Template.RestartState)(OneState->StateReference,
  744.                     FrozenNote->MultisampleFrequency,FrozenNote->Accent1,FrozenNote->Accent2,
  745.                     FrozenNote->Accent3,FrozenNote->Accent4,FrozenNote->LoudnessAdjust,
  746.                     FrozenNote->HurryUpFactor,RetriggerEnvelopes,FrozenNote->StereoPosition,
  747.                     FrozenNote->NominalFrequency,/*LoudnessLFOAmplitudeScaling?*/1,
  748.                     /*LoudnessLFOFrequencyScaling?*/1);
  749.                 OneState = OneState->Next;
  750.             }
  751.  
  752.         LFOGeneratorRetriggerFromOrigin(State->PitchLFO,FrozenNote->Accent1,
  753.             FrozenNote->Accent2,FrozenNote->Accent3,FrozenNote->Accent4,
  754.             FrozenNote->NominalFrequency,FrozenNote->HurryUpFactor,
  755.             State->BankTemplate->EnvelopeUpdateRate,
  756.             FrozenNote->PitchDisplacementDepthLimit / 12,
  757.             FrozenNote->PitchDisplacementRateLimit,RetriggerEnvelopes);
  758.         State->PitchLFOHertz = FrozenNote->PitchDisplacementDepthInHertz;
  759.  
  760.         /* if this object ties to a note, then this is the note to tie to.  this is */
  761.         /* used for finding existing oscillators for tie continuations. */
  762.         State->TieToNote = FrozenNote->OriginalNote->a.Note.Tie;
  763.  
  764.         /* portamento control parameters */
  765.         if (FrozenNote->PortamentoDuration > 0)
  766.             {
  767.                 State->PortamentoCounter = FrozenNote->PortamentoDuration;
  768.                 State->TotalPortamentoTicks = FrozenNote->PortamentoDuration;
  769.                 State->InitialFrequency = State->CurrentFrequency; /* save current pitch */
  770.                 State->FinalFrequency = FrozenNote->NominalFrequency;
  771.                 State->PortamentoHertz = ((FrozenNote->OriginalNote->Flags
  772.                     & ePortamentoHertzNotHalfsteps) != 0);
  773.             }
  774.          else
  775.             {
  776.                 State->PortamentoCounter = 0;
  777.                 State->CurrentFrequency = FrozenNote->NominalFrequency;
  778.             }
  779.  
  780.         /* various counters (in terms of envelope ticks) */
  781.         if (State->TieToNote == NIL)
  782.             {
  783.                 State->Release1Countdown = FrozenNote->ReleasePoint1;
  784.                 State->Release2Countdown = FrozenNote->ReleasePoint2;
  785.                 State->Release3Countdown = FrozenNote->ReleasePoint3;
  786.             }
  787.          else
  788.             {
  789.                 /* for ties, only honor releases from start */
  790.                 if (FrozenNote->Release1FromStart)
  791.                     {
  792.                         State->Release1Countdown = FrozenNote->ReleasePoint1;
  793.                     }
  794.                  else
  795.                     {
  796.                         State->Release1Countdown = -1;
  797.                     }
  798.                 if (FrozenNote->Release2FromStart)
  799.                     {
  800.                         State->Release2Countdown = FrozenNote->ReleasePoint2;
  801.                     }
  802.                  else
  803.                     {
  804.                         State->Release2Countdown = -1;
  805.                     }
  806.                 if (FrozenNote->Release3FromStart)
  807.                     {
  808.                         State->Release3Countdown = FrozenNote->ReleasePoint3;
  809.                     }
  810.                  else
  811.                     {
  812.                         State->Release3Countdown = -1;
  813.                     }
  814.             }
  815.         if (RetriggerEnvelopes)
  816.             {
  817.                 State->PitchLFOStartCountdown = FrozenNote->PitchDisplacementStartPoint;
  818.             }
  819.          else
  820.             {
  821.                 State->PitchLFOStartCountdown = -1;
  822.             }
  823.  
  824.         return True;
  825.     }
  826.  
  827.  
  828. /* get rid of a state bank */
  829. void                                    DisposeOscStateBank(OscStateBankRec* State)
  830.     {
  831.         OscStateRec*                OneStateScan;
  832.  
  833.         CheckPtrExistence(State);
  834.         ValidateOscStateBank(State);
  835.  
  836.         OneStateScan = State->OscillatorList;
  837.         while (OneStateScan != NIL)
  838.             {
  839.                 OscStateRec*                Temp;
  840.  
  841.                 (*OneStateScan->Template.DisposeState)(OneStateScan->StateReference);
  842.                 Temp = OneStateScan;
  843.                 OneStateScan = OneStateScan->Next;
  844.                 Temp->Next = StateFreeList;
  845.                 StateFreeList = Temp;
  846.             }
  847.  
  848.         DisposeLFOGenerator(State->PitchLFO);
  849.  
  850.         State->Next = StateBankFreeList;
  851.         StateBankFreeList = State;
  852.     }
  853.  
  854.  
  855. /* get the reference to the note that this bank ties to.  NIL if it doesn't */
  856. struct NoteObjectRec*    GetOscStateTieTarget(OscStateBankRec* State)
  857.     {
  858.         CheckPtrExistence(State);
  859.         ValidateOscStateBank(State);
  860.  
  861.         return State->TieToNote;
  862.     }
  863.  
  864.  
  865. /* perform one envelope clock cycle on a state bank.  this returns True if the */
  866. /* state bank is done and should be retired.  (it will return false if it is a */
  867. /* tie source.) */
  868. MyBoolean                            UpdateOscStateBank(OscStateBankRec* State, long NumFrames,
  869.                                                 largefixedsigned* OutputData)
  870.     {
  871.         OscStateRec*                OneStateScan;
  872.         MyBoolean                        OscillatorsRunning;
  873.         float                                Frequency;
  874.  
  875.         CheckPtrExistence(State);
  876.         ValidateOscStateBank(State);
  877.  
  878.         if (State->Release1Countdown >= 0)
  879.             {
  880.                 State->Release1Countdown -= 1;
  881.                 if (State->Release1Countdown == 0)
  882.                     {
  883.                         OneStateScan = State->OscillatorList;
  884.                         while (OneStateScan != NIL)
  885.                             {
  886.                                 (*OneStateScan->Template.KeyUpSustain1)(OneStateScan->StateReference);
  887.                                 OneStateScan = OneStateScan->Next;
  888.                             }
  889.                         LFOGeneratorKeyUpSustain1(State->PitchLFO);
  890.                     }
  891.             }
  892.  
  893.         if (State->Release2Countdown >= 0)
  894.             {
  895.                 State->Release2Countdown -= 1;
  896.                 if (State->Release2Countdown == 0)
  897.                     {
  898.                         OneStateScan = State->OscillatorList;
  899.                         while (OneStateScan != NIL)
  900.                             {
  901.                                 (*OneStateScan->Template.KeyUpSustain2)(OneStateScan->StateReference);
  902.                                 OneStateScan = OneStateScan->Next;
  903.                             }
  904.                         LFOGeneratorKeyUpSustain2(State->PitchLFO);
  905.                     }
  906.             }
  907.  
  908.         if (State->Release3Countdown >= 0)
  909.             {
  910.                 State->Release3Countdown -= 1;
  911.                 if (State->Release3Countdown == 0)
  912.                     {
  913.                         OneStateScan = State->OscillatorList;
  914.                         while (OneStateScan != NIL)
  915.                             {
  916.                                 (*OneStateScan->Template.KeyUpSustain3)(OneStateScan->StateReference);
  917.                                 OneStateScan = OneStateScan->Next;
  918.                             }
  919.                         LFOGeneratorKeyUpSustain3(State->PitchLFO);
  920.                     }
  921.             }
  922.  
  923.         /* perform portamento */
  924.         if (State->PortamentoCounter > 0)
  925.             {
  926.                 /* decrement is done before interpolation so that the final frequency */
  927.                 /* will actually be reached. */
  928.                 State->PortamentoCounter -= 1;
  929.                 if (State->PortamentoHertz)
  930.                     {
  931.                         /* this transition is linear, so it's easy to compute */
  932.                         /* L+F(R-L) */
  933.                         State->CurrentFrequency = State->InitialFrequency
  934.                             + ((float)(State->TotalPortamentoTicks
  935.                             - State->PortamentoCounter) / State->TotalPortamentoTicks)
  936.                             * (State->FinalFrequency - State->InitialFrequency);
  937.                     }
  938.                  else
  939.                     {
  940.                         /* this transition is log-linear, so it's a bit messier */
  941.                         State->CurrentFrequency = State->InitialFrequency * (float)FEXP(
  942.                             ((float)(State->TotalPortamentoTicks - State->PortamentoCounter)
  943.                             / State->TotalPortamentoTicks)
  944.                             * (((float)FLN(State->FinalFrequency) / (float)LOG2)
  945.                             - ((float)FLN(State->InitialFrequency) / (float)LOG2)) * LOG2);
  946.                     }
  947.             }
  948.  
  949.         /* update the pitch LFO modulation & figure out what the current pitch is */
  950.         if (State->PitchLFOStartCountdown > 0)
  951.             {
  952.                 State->PitchLFOStartCountdown -= 1;
  953.                 Frequency = State->CurrentFrequency;
  954.             }
  955.          else
  956.             {
  957.                 /* do some pitch stuff */
  958.                 Frequency = FastFixed2Float(LFOGenUpdateCycle(State->PitchLFO,
  959.                     Double2FastFixed(State->CurrentFrequency)));
  960.             }
  961.  
  962.         /* perform a cycle of resampling */
  963.         OscillatorsRunning = False;
  964.         OneStateScan = State->OscillatorList;
  965.         while (OneStateScan != NIL)
  966.             {
  967.                 (*OneStateScan->Template.StateNewFrequency)(OneStateScan->StateReference,Frequency);
  968.                 (*OneStateScan->Template.UpdateEnvelopes)(OneStateScan->StateReference);
  969.                 (*OneStateScan->Template.GenSamples)(OneStateScan->StateReference,NumFrames,OutputData);
  970.                 OscillatorsRunning = OscillatorsRunning || !(*OneStateScan->Template
  971.                     .IsItFinished)(OneStateScan->StateReference);
  972.                 OneStateScan = OneStateScan->Next;
  973.             }
  974.  
  975.         return !OscillatorsRunning;
  976.     }
  977.